package com.itheima.dubbo.mongodb.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.commons.pojo.mongo.Album;
import com.itheima.commons.pojo.mongo.Publish;
import com.itheima.commons.pojo.mongo.TimeLine;
import com.itheima.dubbo.interfaces.PublishApi;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.ArrayList;
import java.util.List;

/**
 * @author yaohu
 * @date 2021/12/7
 * @Version 1.0
 * @describe
 */
@Service
public class PublishApiImpl implements PublishApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void publish(Publish publish) {
        mongoTemplate.save(publish);
    }

    @Override
    public List<Publish> findFriendMovements(Integer page, Integer pagesize, Long userId) {

        // 查询自己的时间线表
        List<TimeLine> timeLines = mongoTemplate.find(new Query()
                        .with(Sort.by(Sort.Order.desc("date")))
                        .with(PageRequest.of(page - 1, pagesize)),
                TimeLine.class, "quanzi_time_line_" + userId);

        // 获取所有发布圈子id集合
        List<ObjectId> publishIds = CollUtil.getFieldValues(timeLines, "publishId", ObjectId.class);

        // 根据发布圈子id查询发布表
        return mongoTemplate.find(Query.query(Criteria.where("id").in(publishIds)), Publish.class);
    }

    @Override
    public List<Publish> randomMovements(Integer pagesize) {

        // 从mongodb中随机抽样数据
        AggregationResults<Publish> aggregationResults = mongoTemplate.aggregate(
                Aggregation.newAggregation(Publish.class, Aggregation.sample(Convert.toLong(pagesize))),
                Publish.class);
        return aggregationResults.getMappedResults();
    }

    @Override
    public List<Publish> findMovementsByPids(List<Long> publishIdList) {

        // 查询quanzi_publish表
        return mongoTemplate.find(Query.query(Criteria.where("pid").in(publishIdList)), Publish.class);
    }

    @Override
    public Publish queryPublishById(String publishId) {

        return mongoTemplate.findById(new ObjectId(publishId), Publish.class);
    }

    /**
     * 分页查询用户发布的圈子信息
     *
     * @param userId   用户ID
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public List<Publish> findMovementsByUserId(Long userId, Integer page, Integer pageSize) {
        List<Album> albumList = mongoTemplate.find(new Query()
                        .with(Sort.by(Sort.Order.desc("created")))
                        .with(PageRequest.of(page - 1, pageSize)),
                Album.class, "quanzi_album_" + userId);

        List<Object> publishIds = CollUtil.getFieldValues(albumList, "publishId");
        return mongoTemplate.find(Query.query(Criteria.where("id").in(publishIds)), Publish.class);
    }

    /**
     * 查询publishInfo中没有的publish信息
     *
     * @param publishIds
     * @return
     */
    @Override
    public List<Publish> findOthers(List<String> publishIds) {
        List<ObjectId> objectIdList = new ArrayList<>();
        for (String publishId : publishIds) {
            objectIdList.add(new ObjectId(publishId));
        }
        return mongoTemplate.find(Query.query(Criteria.where("id").nin(objectIdList)), Publish.class);
    }

    /**
     * 获取最新存储的publish 主要是为了获取publishId 以便存储publishInfo
     *
     * @param userId
     * @return
     */
    @Override
    public Publish queryCurrentPublishByUserId(Long userId) {
        return mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId))
                .with(Sort.by(Sort.Order.desc("created"))), Publish.class);
    }
}
